﻿/*=================================================================================================
// <copyright company="AltaModa Technologies, LLC">
//	Copyright (c) AltaModa Technologies, LLC. All rights reserved.
//	http://www.AltaModaTech.com/
// </copyright>
// 
//	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
//	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
//	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
//	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
//	CONSEQUENTIAL DAMAGES INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
//	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
//	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
//	OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
//	POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================*/

using System.Xml;

namespace AMT.Web.Security
{
	public class ConfigFileMembershipProvider : DenyAllMembershipProvider
	{
		#region Private static, const members
		private static string[] s_EmptyStringArray = new string[] { };
		private const string PROVIDER_CONFIG_ATTRIBITE_NAME = "providerConfigFilePath";
		private const string DEFAULT_PROVIDER_CONFIG_FILE_PATH = "~/Account/MemberRoles.xml";
		#endregion

		#region Private data members
		private string _providerConfigFilePath;
		#endregion

		public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
		{
			base.Initialize(name, config);
			// Get the setting for the xml file's location
			if (null != config[PROVIDER_CONFIG_ATTRIBITE_NAME])
			{
				_providerConfigFilePath = config[PROVIDER_CONFIG_ATTRIBITE_NAME];
			}

			// Use default file path if none was specified in the attribute
			if (null == _providerConfigFilePath || 0 == _providerConfigFilePath.Length)
			{
				_providerConfigFilePath = DEFAULT_PROVIDER_CONFIG_FILE_PATH;
			}

		}

		/// <summary>
		/// Validates user name and password using values from the application's config file
		/// </summary>
		/// <param name="username"></param>
		/// <param name="password"></param>
		/// <returns>True if authenticated; false on username or password mismatch</returns>
		public override bool ValidateUser(string username, string password)
		{
			bool authenticated = false;

			var credentials = LoadUserCredentialsFromConfig();
			foreach (string validUserName in credentials.Keys)
			{
				if (validUserName.ToLower() == username.ToLower())
				{
					if (credentials[validUserName] == password)
					{
						authenticated = true;
						break;
					}
				}
			}

			return authenticated;
		}

		// TODO: move to shared loc; no need for membership, roles, etc. to impl same code
		#region Private methods
		private System.Collections.Specialized.StringDictionary LoadUserCredentialsFromConfig()
		{
			// TODO: consider caching after loading; but consider dev need to make config changes at runtime
			System.Collections.Specialized.StringDictionary usersFromXml = new System.Collections.Specialized.StringDictionary();

			var xml = LoadXmlConfigFile(_providerConfigFilePath);

			foreach (XmlNode node in xml.SelectNodes("/application/user"))
			{
				usersFromXml.Add(node.Attributes["name"].Value, node.Attributes["password"].Value);
			}

			return usersFromXml;
		}

		// TODO: moved to shared lib?
		private XmlDocument LoadXmlConfigFile(string filePath)
		{
			System.Diagnostics.Debug.Assert(null != filePath && 0 < filePath.Length);

			if (System.Web.VirtualPathUtility.IsAppRelative(filePath))
			{
				filePath = System.Web.HttpContext.Current.Server.MapPath(filePath);
			}

			var xml = new XmlDocument();
			xml.Load(filePath);
			return xml;
		}
		#endregion

	}
}
